<?php
/**
 * 易优CMS
 * ============================================================================
 * 版权所有 2016-2028 海口快推科技有限公司，并保留所有权利。
 * 网站地址: http://www.eyoucms.com
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 陈风任 <491085389@qq.com>
 * Date: 2019-1-7
 */

namespace app\common\model;

use think\Db;
use think\Cache;
use think\Config;
use think\Cookie;

/**
 * 商城商品处理模型
 */
load_trait('controller/Jump');
class ShopGoodsHandle
{
    use \traits\controller\Jump;

    private $post = [];
    private $cacheData = [];
    private $usersData = [];
    private $usersConfig = [];
    private $sendTerminal = '';

    // 构造函数
    public function __construct()
    {
        // 统一接收参数处理
        $this->times = getTime();
        $this->post = input('post.');
        $this->goodsList = [];
        $this->cacheData = [];
        $this->usersData = [];
        $this->usersConfig = [];
        $this->globalConfig = [];
        $this->sendTerminal = input('param.sendTerminal/s', 'openSource');
        $this->sendTerminal = !empty($this->sendTerminal) ? trim($this->sendTerminal) : '';
        $this->shopPublicHandleModel = model('ShopPublicHandle');
    }

    // 获取提交购买的商品数据
    public function getBuyGoodsListComment($post = [], $usersData = [], $usersConfig = [])
    {
        // 参数定义
        $this->post = !empty($post) ? $post : $this->post;
        $this->usersData = !empty($usersData) ? $usersData : $this->usersData;
        $this->usersConfig = !empty($usersConfig) ? $usersConfig : $this->usersConfig;

        // 获取缓存内容
        $this->cacheData = Cache::get($this->post['querystr']);
        if (empty($this->cacheData) && !empty($this->post['querystr']) && 'undefined' != $this->post['querystr']) $this->error('链接失效，请重新下单');

        // 获取订单流程所需全局信息
        $this->getGlobalConfig();

        // 获取下单的商品数据
        $this->getBuyGoodsList();

        // 处理下单的商品数据
        $this->handleBuyGoodsList();

        // 返回数据
        return [$this->goodsList, $this->globalConfig];
    }

    // 获取订单流程所需全局信息
    public function getGlobalConfig()
    {
        $this->globalConfig = [
            // 温馨提示内容,为空则不展示
            'shop_prompt' => !empty($this->usersConfig['shop_prompt']) ? $this->usersConfig['shop_prompt'] : '',
            // 是否开启线下支付(货到付款)
            'shop_open_offline' => !empty($this->usersConfig['shop_open_offline']) ? $this->usersConfig['shop_open_offline'] : 0,
            // 是否开启运费设置
            'shop_open_shipping' => !empty($this->usersConfig['shop_open_shipping']) ? $this->usersConfig['shop_open_shipping'] : 0,
            // 初始化支付总额
            'TotalAmount' => 0,
            // 初始化支付总额，包含运费
            'PayTotalAmount' => 0,
            // 初始化总数
            'TotalNumber' => 0,
            // 提交来源:0购物车;1直接下单
            'submit_order_type' => !empty($this->cacheData) ? 1 : 0,
            // 1表示为虚拟订单
            'PromType' => 1,
            // 虚拟订单文案
            'virtual_text1' => '1、该产品为虚拟产品，仅支持在线支付且无需选择收货地址及运费计算。',
            'virtual_text2' => '2、若产品是充值类产品，请将您的手机号或需充值的卡号填入留言中。',
            // 秒杀商品ID
            'seckillActID'       => 0,
            'seckillGoodsID'     => 0,
            // 仅到店核销
            'onlyVerify'         => false,
            // 仅物流配送
            'onlyDelivery'       => false,
            // 物流支持
            'allLogisticsType'   => false,
        ];
    }

    // 获取下单的商品数据
    public function getBuyGoodsList()
    {
        // 单商品购买
        if (!empty($this->cacheData)) {
            $seckillGoods = [];
            // 秒杀商品则查询秒杀活动相关内容
            if (!empty($this->cacheData['goods_id'])) {
                // 查询秒杀商品是否存在
                $seckillGoods = Db::name('weapp_seckill_archives')->where('goods_id', $this->cacheData['goods_id'])->find();
                if (empty($seckillGoods['act_id'])) $this->error('秒杀商品不存在');
                // 查询秒杀活动是否可用
                $seckillActiv = Db::name('weapp_seckill')->field('status, in_progress, end_time')->where('id', $seckillGoods['act_id'])->find();
                if (empty($seckillActiv)) $this->error('秒杀活动不存在');
                if ($this->times > $seckillActiv['end_time']) $this->error('秒杀活动已结束');
                if (empty($seckillActiv['in_progress']) || 1 !== intval($seckillActiv['status'])) $this->error('秒杀活动未开启');
            }

            // 查询商品条件
            $where['a.aid'] = intval($this->cacheData['product_id']);
            if (!empty($this->cacheData['spec_value_id'])) {
                $where['b.spec_value_id'] = trim($this->cacheData['spec_value_id']);
                // 秒杀商品条件
                if (!empty($seckillGoods['goods_id'])) {
                    $where['c.goods_id'] = intval($seckillGoods['goods_id']);
                    $where['c.spec_value_id'] = trim($this->cacheData['spec_value_id']);
                }
            }

            // 查询商品字段
            $field = 'a.aid, a.stypeid, a.title, a.litpic, a.users_price, a.users_discount_type, a.stock_count, a.prom_type, a.attrlist_id, a.logistics_type, b.value_id, b.aid as product_id, b.spec_value_id, b.spec_price, b.spec_stock';
            // 秒杀商品字段
            if (!empty($seckillGoods['goods_id'])) $field .= ', c.goods_id, c.seckill_price, c.seckill_stock';

            // 查询商品
            $joinSql = Db::name('archives')->alias('a')->field($field)->join('__PRODUCT_SPEC_VALUE__ b', 'a.aid = b.aid', 'LEFT');
            // 秒杀商品查询指定的数据表
            if (!empty($seckillGoods['goods_id'])) $joinSql = $joinSql->join('__WEAPP_SECKILL_PRODUCT_SPEC_VALUE__ c', 'a.aid = c.aid', 'LEFT');
            // 执行查询
            $goodsData = $joinSql->where($where)->find();// ->limit('0, 1')->select();
            if (empty($goodsData)) $this->error('商品不存在');

            // 购买商品
            $goodsData['product_id'] = empty($goodsData['product_id']) ? intval($this->cacheData['product_id']) : intval($goodsData['product_id']);
            // 购买数量
            $goodsData['product_num'] = empty($goodsData['product_num']) ? intval($this->cacheData['product_num']) : intval($goodsData['product_num']);

            // 秒杀处理
            if (!empty($seckillGoods)) {
                // 商品数据处理
                $goodsData['goods_id'] = empty($goodsData['goods_id']) ? intval($this->cacheData['goods_id']) : intval($goodsData['goods_id']);

                // 秒杀库存不能大于商品规格库存
                if (intval($goodsData['seckill_stock']) > intval($goodsData['spec_stock'])) $goodsData['seckill_stock'] = intval($goodsData['spec_stock']);

                // 秒杀商品 && 单规格则执行
                if (empty($seckillGoods['is_spec'])) {
                    // 价格处理
                    $goodsData['users_price'] = $goodsData['seckill_price'] = unifyPriceHandle($seckillGoods['seckill_price']);
                    // 秒杀库存不能大于商品库存
                    if (intval($seckillGoods['seckill_stock']) > intval($goodsData['stock_count'])) {
                        $goodsData['seckill_stock'] = $seckillGoods['seckill_stock'] = intval($goodsData['stock_count']);
                    } else {
                        $goodsData['stock_count'] = $goodsData['seckill_stock'] = intval($seckillGoods['seckill_stock']);
                    }
                }

                // 秒杀商品ID
                $this->globalConfig['seckillActID'] = intval($seckillGoods['act_id']);
                $this->globalConfig['seckillGoodsID'] = intval($seckillGoods['goods_id']);
            }

            $list = [$goodsData];
        }
        // 购物车购买
        else {
            // 购物车下单
            $where = [
                'b.is_del' => 0,
                'a.selected' => 1,
                'a.users_id' => $this->usersData['users_id'],
                'b.arcrank'  => array('egt', 0),
            ];
            $field = 'a.*, b.stypeid, b.aid, b.title, b.litpic, b.users_price, b.users_discount_type, b.stock_count, b.prom_type, b.attrlist_id, b.logistics_type, c.spec_price, c.spec_stock, c.value_id';
            $list = Db::name('shop_cart')->alias('a')
                ->field($field)
                ->join('__ARCHIVES__ b', 'a.product_id = b.aid', 'LEFT')
                ->join('__PRODUCT_SPEC_VALUE__ c', 'a.spec_value_id = c.spec_value_id and a.product_id = c.aid', 'LEFT')
                ->where($where)
                ->select();
            $logisticsTypeArr = get_arr_column($list, 'logistics_type');
            if (empty($post['deliveryShow']) && empty($post['verifyShow']) && in_array(1, $logisticsTypeArr)) $post['deliveryShow'] = 1;
            foreach ($list as $key => $value) {
                // 仅购买支持到店核销商品
                if (!empty($post['verifyShow']) && 1 === intval($post['verifyShow'])) {
                    if ('1' === $value['logistics_type']) unset($list[$key]);
                }
                // 仅购买支持快递配送商品
                else if (!empty($post['deliveryShow']) && 1 === intval($post['deliveryShow'])) {
                    if ('2' === $value['logistics_type']) unset($list[$key]);
                }
            }
        }
        if (empty($list)) $this->error('链接失效，请重新下单');

        // 赋值结束
        $this->goodsList = $list;
    }

    // 商品规格/折扣数据处理
    public function handleBuyGoodsList()
    {
        // 会员折扣率
        $usersDiscount = !empty($this->usersData['level_discount']) ? strval($this->usersData['level_discount']) / strval(100) : 1;
        foreach ($this->goodsList as $key => $value) {
            // 图片处理
            $value['litpic'] = get_default_pic($value['litpic'], true);

            // 规格处理
            $value['product_spec_list'] = !empty($value['spec_value_id']) ? $this->shopPublicHandleModel->getGoodsSpecList($value) : [];

            // 秒杀商品处理
            if (!empty($value['goods_id'])) {
                // 秒杀库存覆盖商品库存
                if (!empty($value['seckill_stock'])) $value['stock_count'] = intval($value['seckill_stock']);
                // 商品存在规格且价格不为空，则覆盖商品原来的价格
                if (!empty($value['product_spec_list']) && $value['seckill_price'] >= 0) $value['users_price'] = unifyPriceHandle($value['seckill_price']);
            }
            // 普通商品处理
            else {
                // 规格库存覆盖商品库存
                if (!empty($value['spec_stock'])) $value['stock_count'] = intval($value['spec_stock']);
                // 商品存在规格且价格不为空，则覆盖商品原来的价格
                if (!empty($value['product_spec_list']) && $value['spec_price'] >= 0) $value['users_price'] = unifyPriceHandle($value['spec_price']);
            }

            // 商品无折扣原价
            $value['old_price'] = unifyPriceHandle($value['users_price']);

            // 计算会员折扣价，商品设置随会员折扣计算 且 不是秒杀商品 则执行计算
            if (0 === intval($value['users_discount_type']) && !empty($usersDiscount) && empty($value['goods_id'])) {
                $value['users_price'] = unifyPriceHandle($value['users_price'] * $usersDiscount);
            }
            // 商品独立会员折扣价，单规格商品设置会员折扣价 且 不是秒杀商品 则执行处理
            else if (1 === intval($value['users_discount_type']) && empty($value['product_spec_list']) && !empty($this->usersData['level_id']) && empty($value['goods_id'])) {
                $value['users_price'] = $this->shopPublicHandleModel->handleUsersDiscountPrice($value['aid'], $this->usersData['level_id']);
            }

            // 购买数量超过最大库存量则默认购买最大库存量
            if (intval($value['product_num']) > intval($value['stock_count'])) $value['product_num'] = intval($value['stock_count']);

            // 若库存为空则清除这条数据
            if (empty($value['stock_count'])) {
                unset($this->goodsList[$key]);
                continue;
            }

            $this->goodsList[$key] = $value;
        }
        if (empty($this->goodsList)) $this->error('商品库存不足或已过期');

        // 商品数据整合处理
        foreach ($this->goodsList as $key => $value) {
            // 合计金额、合计数量计算
            if (floatval($value['users_price']) >= 0 && !empty($value['product_num'])) {
                // 计算单品小计
                $value['subtotal'] = unifyPriceHandle($value['users_price'] * $value['product_num']);
                // 计算合计金额
                $this->globalConfig['TotalAmount'] += $value['subtotal'];
                $this->globalConfig['TotalAmount'] = unifyPriceHandle($this->globalConfig['TotalAmount']);
                // 计算合计数量
                $this->globalConfig['TotalNumber'] += $value['product_num'];
                // 判断订单类型，目前逻辑：一个订单中，只要存在一个普通商品(实物商品，需要发货物流)，则为普通订单
                // 0表示为普通订单，1表示为虚拟订单，虚拟订单无需发货物流，无需选择收货地址，无需计算运费
                if (empty($value['prom_type'])) $this->globalConfig['PromType'] = 0;
            }

            // 规格处理
            $value['product_spec'] = '';
            $spec_value_id = !empty($value['spec_value_id']) ? explode('_', $value['spec_value_id']) : [];
            if (!empty($spec_value_id)) {
                $where = [
                    'aid' => intval($value['product_id']),
                    'spec_value_id' => ['IN', $spec_value_id]
                ];
                $productSpecData = Db::name("product_spec_data")->where($where)->field('spec_name, spec_value')->select();
                foreach ($productSpecData as $spec_value) {
                    $value['product_spec'] .= $spec_value['spec_value'] . '；';
                }
            }
            $this->goodsList[$key] = $value;

            $verify_open = 0;
            // 如果安装了核销插件则执行
            if (is_dir('./weapp/Verify/')) {
                // 核销插件数据信息
                $verifyInfo = model('Weapp')->getWeappList('Verify');
                if (!empty($verifyInfo['status']) && !empty($verifyInfo['data']['openVerify'])) $verify_open = 1;
            }
            // 仅物流配送
            if ('1' === $value['logistics_type']) $this->globalConfig['onlyDelivery'] = true;
            // 仅到店核销
            if ('2' === $value['logistics_type'] && !empty($verify_open)) $this->globalConfig['onlyVerify'] = true;
            // 物流配送 和 到店核销 都支持
            if ('1,2' === $value['logistics_type']) {
                if (!empty($verify_open)) {
                    $this->globalConfig['allLogisticsType'] = true;
                } else {
                    $this->globalConfig['onlyDelivery'] = true;
                }
            }
            // // 仅到店核销
            // if ('2' === $value['logistics_type']) $this->globalConfig['onlyVerify'] = true;
            // // 仅物流配送
            // if ('1' === $value['logistics_type']) $this->globalConfig['onlyDelivery'] = true;
            // // 物流配送 和 到店核销 都支持
            // if ('1,2' === $value['logistics_type']) $this->globalConfig['allLogisticsType'] = true;
        }
    }

    // 查询验证所购买的商品是否存库充足
    public function verifyGoodsStockCount($post = [])
    {
        // 秒杀商品
        if (!empty($post['goods_id'])) {
            // 查询所购买商品是否在售状态
            $where = [
                'aid' => intval($post['product_id']),
                'goods_id' => intval($post['goods_id'])
            ];
            $stockCount = Db::name('weapp_seckill_archives')->where($where)->getField('seckill_stock');
            if (!isset($stockCount)) $this->error('选购的商品不存在');

            // 多规格商品则查询规格库存
            if (!empty($post['spec_value_id'])) {
                $where = [
                    'aid' => intval($post['product_id']),
                    'goods_id' => intval($post['goods_id']),
                    'spec_value_id' => trim($post['spec_value_id'])
                ];
                $stockCount = Db::name('weapp_seckill_product_spec_value')->where($where)->getField('seckill_stock');
            }
        }
        // 普通商品
        else {
            // 查询所购买商品是否在售状态
            $where = [
                'aid' => intval($post['product_id']),
                'arcrank' => ['egt', 0]
            ];
            $stockCount = Db::name('archives')->where($where)->getField('stock_count');
            if (!isset($stockCount)) $this->error('选购的商品不存在');

            // 多规格商品则查询规格库存
            if (!empty($post['spec_value_id'])) {
                $where  = [
                    'aid' => intval($post['product_id']),
                    'spec_value_id' => trim($post['spec_value_id'])
                ];
                $stockCount = Db::name('product_spec_value')->where($where)->getField('spec_stock');
            }
        }

        // 判断是否可以购买
        if (empty($stockCount)) $this->error('选购的商品已售罄');
        if (intval($stockCount) < intval($post['product_num'])) $this->error('选购的商品库存不足，最大库存: ' . $stockCount);
    }

    // 获取商品信息加密串
    public function getGoodsQueryStr($post = [])
    {
        // 商品ID及购买数量
        $queryData = [
            'product_id'  => intval($post['product_id']),
            'product_num' => intval($post['product_num']),
        ];
        // 秒杀商品ID
        if (!empty($post['goods_id'])) $queryData['goods_id'] = intval($post['goods_id']);
        // 商品规格ID
        if (!empty($post['spec_value_id']) && 'undefined' != $post['spec_value_id']) $queryData['spec_value_id'] = trim($post['spec_value_id']);
        // 先 json_encode 后 md5 加密信息
        $queryStr = md5(json_encode($queryData));
        // 存入缓存，一天有效期
        Cache::set($queryStr, $queryData, 86400);

        // 返回加密串
        return $queryStr;
    }
}